package com.gzdh.tang.qimei.rule;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePayRequest;
import com.alipay.api.response.AlipayTradePayResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gzdh.tang.ali.model.OuterExtends;
import com.gzdh.tang.comm.constant.SpringContextUtils;
import com.gzdh.tang.comm.handler.IPayRuleHandler;
import com.gzdh.tang.config.ali.AliPayUtil;
import com.gzdh.tang.dishrecognition.model.WeekMenuBakModelReq;
import com.gzdh.tang.modu.entity.*;
import com.gzdh.tang.modu.model.dk.JsonsRootBean;
import com.gzdh.tang.modu.service.*;
import com.gzdh.tang.modu.util.DateUtil;
import com.gzdh.tang.qimei.model.LineConsumeReq;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.List;

@Slf4j
public class QimeiPayRule implements IPayRuleHandler {

    FkService fkService;

    GsService gsService;

    MacMainpSbruanService macMainpSbruanService;

    MacMainpSbruanDinnerService macMainpSbruanDinnerService;

    MacMainpSbruanKlService macMainpSbruanKlService;

    ReserveService reserveService;

    ReserveXfjTempService reserveXfjTempService;
    TangAddrService tangAddrService;

    public QimeiPayRule() {
        fkService = (FkService) SpringContextUtils.getBean("fkServiceImpl");
        gsService = (GsService) SpringContextUtils.getBean("gsService");
        macMainpSbruanService = (MacMainpSbruanService) SpringContextUtils.getBean("macMainpSbruanService");
        macMainpSbruanDinnerService = (MacMainpSbruanDinnerService) SpringContextUtils.getBean("macMainpSbruanDinnerService");
        macMainpSbruanKlService = (MacMainpSbruanKlService) SpringContextUtils.getBean("macMainpSbruanKlService");
        reserveService = (ReserveService) SpringContextUtils.getBean("reserveService");
        reserveXfjTempService = (ReserveXfjTempService) SpringContextUtils.getBean("reserveServiceXfjTemp");
        tangAddrService = (TangAddrService) SpringContextUtils.getBean("tangAddrServiceImpl");
    }

    /**
     * 发起Card
     * 先获取菜品，获取FK表信息
     *
     * @param params
     * @return
     */
    @Override
    public JSONObject toCardPay(JSONObject params) throws RuntimeException {


        LineConsumeReq lineConsumeReq = params.getJSONObject("req").toJavaObject(LineConsumeReq.class);
        String cardSn = params.getString("cardSn");
        String foodsImg = "/sys/common/static/" + params.getString("imgPath");
        BigDecimal xfPirce = new BigDecimal(lineConsumeReq.getMoney()).divide(new BigDecimal(100));
        Fk fk = null;
        List<Fk> fkList = fkService.list(new QueryWrapper<Fk>().lambda().eq(Fk::getCardsn, cardSn));
        if (fkList.size() > 1) {
            throw new RuntimeException("刷卡失败：请联系管理员：#101");
        } else if (fkList.size() > 0) {
            fk = fkList.get(0);
        } else {
            throw new RuntimeException("非法卡");
        }
        String sc = "0";
        BigDecimal cardPrice = new BigDecimal(0);
        BigDecimal kye = new BigDecimal(fk.getKye());
        BigDecimal btye = new BigDecimal(fk.getBtye());
        if (btye.compareTo(xfPirce) >= 0) {
            sc = "1";
            cardPrice = btye;
        } else if (kye.compareTo(xfPirce) >= 0) {
            sc = "0";
            cardPrice = kye;
        } else {
            throw new RuntimeException("余额不足");
        }
        int count = gsService.count(new QueryWrapper<Gs>().lambda().eq(Gs::getKh, fk.getKh()).eq(Gs::getCardno, fk.getCardno()));
        if (count > 0) {
            throw new RuntimeException("此卡已挂失,请回收");
        }
        MacMainpSbruan macMainpSbruan = macMainpSbruanService.getOne(new QueryWrapper<MacMainpSbruan>()
                .lambda().eq(MacMainpSbruan::getMac, lineConsumeReq.getDeviceId()));
        try {
            String dinner = getDinner(macMainpSbruan).trim();
            macMainpSbruan.setDinner(dinner);
        } catch (Exception e) {
            throw new RuntimeException("餐次获取失败");
        }
        List<MacMainpSbruanKl> macMainpSbruanKlList = macMainpSbruanKlService.list(new QueryWrapper<MacMainpSbruanKl>().lambda()
                .eq(MacMainpSbruanKl::getDeviceId, macMainpSbruan.getId()));
        if (!judeKl(macMainpSbruanKlList, fk.getKl())) {
            throw new RuntimeException("不支持此卡类");
        }
        int temp = 0;
        for (LineConsumeReq.Menu goo : lineConsumeReq.getMenuArray()) {
            //插入RESERVE
            insertReserve(
                    lineConsumeReq.getConsumptionNumber(),
                    lineConsumeReq.getConsumptionNumber(),
                    cardSn,
                    goo.getMenuPrice(),
                    goo.getMenuCount(),
                    fk, macMainpSbruan,
                    goo.getMenuName(),
                    StringUtils.isEmpty(goo.getMenuId()) ? "" : goo.getMenuId(),
                    cardPrice,
                    sc, temp++, foodsImg);
        }
        fk = fkService.getOne(new QueryWrapper<Fk>().lambda().eq(Fk::getCardno, fk.getCardno()));
        JSONObject resJson = new JSONObject();
        resJson.put("fk", fk);
        return resJson;
    }

    private String getDinner(MacMainpSbruan macMainpSbruan) throws Exception {
        String hourMin = new SimpleDateFormat("HH:mm").format(new Date());
        List<MacMainpSbruanDinner> macMainpSbruanDinnerList = macMainpSbruanDinnerService
                .list(new QueryWrapper<MacMainpSbruanDinner>().lambda()
                        .eq(MacMainpSbruanDinner::getDeviceId, macMainpSbruan.getId()));
        for (MacMainpSbruanDinner goo : macMainpSbruanDinnerList) {
            if (DateUtil.hourMinuteBetween(hourMin, goo.getStartTime(), goo.getEndTime())) {
                return goo.getDinner();
            }
        }
        throw new Exception("未找到该灶类");
    }

    private boolean judeKl(List<MacMainpSbruanKl> macMainpSbruanKlList, String kl) {
        for (MacMainpSbruanKl goo : macMainpSbruanKlList) {
            if (goo.getKl().equals(kl.trim())) {
                return true;
            }
        }
        return false;
    }

    private boolean insertReserve(String rgTermSN, String reqSeqNo, String cardsn, int price, int sl,
                                  Fk fk, MacMainpSbruan macMainpSbruan, String hName, String code,
                                  BigDecimal cardPrice, String sc, int temp, String foodsImg) throws RuntimeException {
        BigDecimal xfPrice = new BigDecimal(price).divide(new BigDecimal(100));
        BigDecimal yePrice = cardPrice.subtract(xfPrice);
        Date date = new Date();
        Reserve reserve = new Reserve();
        reserve.setCardno(fk.getCardno());
        reserve.setZl(macMainpSbruan.getZl());
        reserve.setBqh(macMainpSbruan.getBqh());
        reserve.setKsh(macMainpSbruan.getKsh());
        reserve.setBed("0");
        reserve.setPosnum(macMainpSbruan.getPos());
        reserve.setDinner(macMainpSbruan.getDinner());
        reserve.setCode(macMainpSbruan.getCode());
        reserve.setSl(sl);
        reserve.setJe((new BigDecimal(price).multiply(new BigDecimal(sl)))
                .divide(new BigDecimal(100), RoundingMode.DOWN).toPlainString());
        reserve.setOriginalAmount(reserve.getJe());
        reserve.setDiscountAmount("0");
        try {
            reserve.setYe(yePrice.setScale(2, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString());
        } catch (Exception e) {
            log.error("余额错误");
            reserve.setYe("0");
        }
        reserve.setKl(fk.getKl());
        reserve.setSc(sc);
        reserve.setLsh2(String.valueOf(reqSeqNo));
        reserve.setCzrq(new Date(date.getTime() + (temp * 10)));
        reserve.setDcrq(new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(new Date()));
        reserve.setHname(hName);
        reserve.setSddz(rgTermSN);
        reserve.setCs(0);
        reserve.setOpenid(cardsn);
        reserve.setKehu(fk.getName());
        reserve.setZfserialnumber("ICZF" + reqSeqNo);
        reserve.setAddr(macMainpSbruan.getAddr());
        reserve.setFoodsImg(foodsImg);
        reserveService.save(reserve);
        return true;
    }

    private boolean insertReserveXfj(String rgTermSN, String reqSeqNo, int price, int sl,
                                     Fk fk, MacMainpSbruan macMainpSbruan, String hName, String code,
                                     BigDecimal cardPrice, String sc, int temp, String order, Date date) throws RuntimeException {
        BigDecimal xfPrice = new BigDecimal(price).divide(new BigDecimal(100));
        BigDecimal yePrice = new BigDecimal(0);

        yePrice = cardPrice.subtract(xfPrice);
        ReserveXfjTemp reserve = new ReserveXfjTemp();
        reserve.setCardno(fk.getCardno());
        reserve.setZl(macMainpSbruan.getZl());
        reserve.setBqh(macMainpSbruan.getBqh());
        reserve.setKsh(macMainpSbruan.getKsh());
        reserve.setBed("0");
        reserve.setPosnum(macMainpSbruan.getPos());
        reserve.setDinner(macMainpSbruan.getDinner());
        reserve.setCode(macMainpSbruan.getCode());
        reserve.setSl(sl);
        reserve.setJe((new BigDecimal(price).multiply(new BigDecimal(sl)))
                .divide(new BigDecimal(100)).toPlainString());
        try {
            reserve.setYe(yePrice.setScale(2, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString());
        } catch (Exception e) {
            log.error("余额错误");
            reserve.setYe("0");
        }
        reserve.setKl(fk.getKl());
        reserve.setSc(sc);
        reserve.setLsh2(order);
        reserve.setCzrq(new Date(date.getTime() + (temp * 10)));
        reserve.setDcrq(new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(new Date()));
        reserve.setHname(hName);
        reserve.setSddz(rgTermSN);
        reserve.setCs(0);

        reserve.setKehu(fk.getName());
        reserve.setZfserialnumber(order);
        reserve.setAddr(macMainpSbruan.getAddr());
        reserveXfjTempService.save(reserve);
        return true;
    }


    /**
     * 现金支付
     *
     * @param params
     * @return
     * @throws RuntimeException
     */
    @Override
    public JSONObject toCashPay(JSONObject params) throws RuntimeException {


        return null;
    }


    @Override
    public JSONObject toQrPay(JSONObject params) throws RuntimeException {
        //掃電子飯卡

        LineConsumeReq lineConsumeReq = params.getJSONObject("req").toJavaObject(LineConsumeReq.class);

        String code = params.getString("code");//授權碼
        byte[] bytes = Base64.getDecoder().decode(code);
        String json = new String(bytes);
        String cardno = json.split(",")[0].split("=")[1];
        String dates = json.split(",")[2].split("=")[1];

        String nowDate = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date(System.currentTimeMillis() - (2 * (60 * 1000) * 60)));
        if (new BigDecimal(nowDate).compareTo(new BigDecimal(dates)) > 0) {
            throw new RuntimeException("二维码已过期");
        }

        String foodsImg = "/sys/common/static/" + params.getString("imgPath");
        BigDecimal xfPirce = new BigDecimal(lineConsumeReq.getMoney()).divide(new BigDecimal(100), RoundingMode.DOWN);
        Fk fk;
        List<Fk> fkList = fkService.list(new QueryWrapper<Fk>().lambda().eq(Fk::getCardno, cardno));
        if (fkList.size() > 1) {
            throw new RuntimeException("刷卡失败：请联系管理员：#101");
        } else if (fkList.size() > 0) {
            fk = fkList.get(0);
        } else {
            throw new RuntimeException("非法卡");
        }
        String sc;
        BigDecimal cardPrice;
        BigDecimal kye = new BigDecimal(fk.getKye());
        BigDecimal btye = new BigDecimal(fk.getBtye());
        if (btye.compareTo(xfPirce) >= 0) {
            sc = "1";
            cardPrice = btye;
        } else if (kye.compareTo(xfPirce) >= 0) {
            sc = "0";
            cardPrice = kye;
        } else {
            throw new RuntimeException("余额不足");
        }
        int count = gsService.count(new QueryWrapper<Gs>().lambda().eq(Gs::getKh, fk.getKh()).eq(Gs::getCardno, fk.getCardno()));
        if (count > 0) {
            throw new RuntimeException("此卡已挂失,请回收");
        }
        MacMainpSbruan macMainpSbruan = macMainpSbruanService.getOne(new QueryWrapper<MacMainpSbruan>()
                .lambda().eq(MacMainpSbruan::getMac, lineConsumeReq.getDeviceId()));
        try {
            String dinner = getDinner(macMainpSbruan).trim();
            macMainpSbruan.setDinner(dinner);
        } catch (Exception e) {
            throw new RuntimeException("餐次获取失败");
        }
        List<MacMainpSbruanKl> macMainpSbruanKlList = macMainpSbruanKlService.list(new QueryWrapper<MacMainpSbruanKl>().lambda()
                .eq(MacMainpSbruanKl::getDeviceId, macMainpSbruan.getId()));
        if (!judeKl(macMainpSbruanKlList, fk.getKl())) {
            throw new RuntimeException("不支持此卡类");
        }
        int temp = 0;
        for (LineConsumeReq.Menu goo : lineConsumeReq.getMenuArray()) {
            //插入RESERVE
            insertReserve(
                    lineConsumeReq.getConsumptionNumber(),
                    lineConsumeReq.getConsumptionNumber(),
                    "QRCode",
                    goo.getMenuPrice(),
                    goo.getMenuCount(),
                    fk, macMainpSbruan,
                    goo.getMenuName(),
                    StringUtils.isEmpty(goo.getMenuId()) ? "" : goo.getMenuId(),
                    cardPrice,
                    sc, temp++, foodsImg);
        }
        fk = fkService.getOne(new QueryWrapper<Fk>().lambda().eq(Fk::getCardno, fk.getCardno()));
        JSONObject resJson = new JSONObject();
        resJson.put("fk", fk);
        return resJson;
    }

    @Override
    public JSONObject toFacePay(JSONObject params) throws RuntimeException {
        //支付宝刷脸
        LineConsumeReq lineConsumeReq = params.getJSONObject("req").toJavaObject(LineConsumeReq.class);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String foodsImg = "/sys/common/static/" + params.getString("imgPath");
        String deviceId = lineConsumeReq.getDeviceId();
        BigDecimal price = new BigDecimal(lineConsumeReq.getMoney()).divide(new BigDecimal(100), RoundingMode.DOWN);
        String authCode = lineConsumeReq.getCode();
        String orders = sdf.format(new Date()) + deviceId;
        String aliUid = lineConsumeReq.getIdentifiedId();

        String terminalParams = lineConsumeReq.getConsumptionUserPK();
        JSONObject jsonObject = new JSONObject();
        jsonObject.putAll(params);
        Fk fk = fkService.getOne(new QueryWrapper<Fk>().lambda().eq(Fk::getAliUserId, aliUid));
        if (fk == null) {
            throw new RuntimeException("非法卡");
        }

        String enterprisePayAmount = "0.00";
        MacMainpSbruan macMainpSbruan = macMainpSbruanService.getOne(new QueryWrapper<MacMainpSbruan>().lambda()
                .eq(MacMainpSbruan::getMac, deviceId));

        Addr addr = tangAddrService.getOne(new QueryWrapper<Addr>().lambda().eq(Addr::getAddrNo, macMainpSbruan.getAddr()));

        try {
            String dinner = getDinner(macMainpSbruan).trim();
            macMainpSbruan.setDinner(dinner);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("餐次获取失败");
        }
        int sc = 0;
        if (new BigDecimal(fk.getBtye()).compareTo(price) >= 0) {
            sc = 1;
            enterprisePayAmount = fk.getBtye();
        } else if (new BigDecimal(fk.getKye()).compareTo(price) >= 0) {
            sc = 0;
            enterprisePayAmount = fk.getKye();
        } else {
            sc = 4;
        }
        int temp = 0;
        for (LineConsumeReq.Menu goo : lineConsumeReq.getMenuArray()) {
            //插入RESERVE
            insertReserveXfj(
                    lineConsumeReq.getConsumptionNumber(),
                    lineConsumeReq.getConsumptionNumber(),

                    goo.getMenuPrice(),
                    goo.getMenuCount(),
                    fk, macMainpSbruan,
                    goo.getMenuName(),
                    StringUtils.isEmpty(goo.getMenuId()) ? "" : goo.getMenuId(),
                    new BigDecimal(enterprisePayAmount),
                    String.valueOf(sc), temp++, orders, new Date());
        }
        try {
            AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
                    AliPayUtil.getAppid(), AliPayUtil.getPrivateKey(),
                    "json", "GBK", AliPayUtil.getPublicKey(),
                    "RSA2");
            AlipayTradePayRequest request = new AlipayTradePayRequest();
            JsonsRootBean jsonsRootBean = new JsonsRootBean(orders, price.toPlainString(),
                    authCode, AliPayUtil.getAssignJointAccountId(), enterprisePayAmount,
                    terminalParams);
            request.setBizContent(JSONObject.toJSONString(jsonsRootBean));
            AlipayTradePayResponse response = alipayClient.execute(request, null, addr.getAliAppAuthToken());
            if (!response.isSuccess()) {
                throw new RuntimeException("支付失败");
            }
            if (!response.getEnterprisePayInfo().getIsUseEnterprisePay()) {
                sc = 4;
                temp = 0;
                for (LineConsumeReq.Menu goo : lineConsumeReq.getMenuArray()) {
                    //插入RESERVE
                    insertReserve(
                            lineConsumeReq.getConsumptionNumber(),
                            lineConsumeReq.getConsumptionNumber(),
                            "",
                            goo.getMenuPrice(),
                            goo.getMenuCount(),
                            fk, macMainpSbruan,
                            goo.getMenuName(),
                            StringUtils.isEmpty(goo.getMenuId()) ? "" : goo.getMenuId(),
                            new BigDecimal(0),
                            "4", temp++, foodsImg);
                }
            } else {
                List<ReserveXfjTemp> reserveXfjTempList = reserveXfjTempService.list(
                        new QueryWrapper<ReserveXfjTemp>().lambda().eq(ReserveXfjTemp::getLsh2, orders)
                );
                List<Reserve> reserveList = new ArrayList<>();
                for (ReserveXfjTemp goo : reserveXfjTempList) {
                    Reserve reserve = new Reserve();
                    BeanUtils.copyProperties(goo, reserve);
                    reserveList.add(reserve);
                }
                reserveService.saveBatch(reserveList);
            }
            fk = fkService.getOne(new QueryWrapper<Fk>().lambda().eq(Fk::getCardno, fk.getCardno()));
            JSONObject resJson = new JSONObject();
            resJson.put("fk", fk);
            resJson.put("macMainpSbruan", macMainpSbruan);
            resJson.put("order", orders);
            resJson.put("amount", price.toPlainString());
            return resJson;
        } catch (Exception e) {
            throw new RuntimeException("支付失败");
        }


    }
}
